home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr48 / ini_api.zip / INI_API.PAS next >
Pascal/Delphi Source File  |  1993-06-15  |  13KB  |  439 lines

  1. { ======================================================================= }
  2. { File: INI_API.PAS                                                       }
  3. { Description: Provides DOS Pascal programs with an .INI or .CFG file     }
  4. {              handler comparable to the Windows 'Profile...' API         }
  5. {              functions.                                                 }
  6. { Requirements: Comments MUST begin in column 1, cannot begin with a '['  }
  7. {               and cannot contain an equals sign (at the moment).        }
  8. { Author: Thomas Hill, dba t.h.ink Software                               }
  9. { Revision History:                                                       }
  10. {   Version 0.0 - First working version  6/03/93                          }
  11. {   Version 1.0 - Cleaned up enough for public viewing.                   }
  12. {                                                                         }
  13. { Synopsis: Currently reads the ENTIRE .INI (or .CFG, or whatever) file   }
  14. {           into memory and creates a two tier structure of Section       }
  15. {           titles and collections of 'entries' for each section.         }
  16. {           All reads and updates act upon the in-memory image.           }
  17. {           If the UpdateNow flag is set, any writes are immdeiately      }
  18. {           save to disk, otherwise it is the programmer's responsibility }
  19. {           to explicitly re-write the initialization file before ending. }
  20. { ======================================================================= }
  21.  
  22. unit INI_API;
  23.  
  24. interface
  25.  
  26. uses Strings;
  27.  
  28. { Error enumeration types }
  29.   type
  30.       INIErrorType = (INI_NOERROR,INI_INVALID_FILE,INI_NO_FILE,INI_BAD_CREATE,
  31.                       INI_BAD_WRITE,INI_BAD_READ);
  32.   const
  33.       INIErrorStr : array[0..5] of pChar =
  34.                     ('INI File: No Error','INI File: Invalid File',
  35.                      'INI File: File Not Found','INI File: Cannot Create File',
  36.                      'INI File: Cannot write File','INI File: Cannot Read File');
  37.  
  38. { Write data to a .INI file. Returns TRUE if successful }
  39.   function WriteProfileString(Section : pChar; { section: [section] }
  40.                               Entry : pChar;   { entry:   entry=data }
  41.                               Data : pChar) : boolean;
  42.  
  43. { get data associated with 'entry', under 'section'. }
  44. { Returns data in 'Target', or places 'Default' in target, if entry/section }
  45. { is not found. }
  46.   function ReadProfileString(Section : pChar;
  47.                              Entry : pChar;
  48.                              Default : pChar;  { default value if Entry not found }
  49.                              Target : pChar;   { where to put the answer }
  50.                              ByteCnt : integer { size of target buffer }
  51.                              ) : boolean;
  52.  
  53. { Deletes entry under 'section' title.  Returns FALSE if delete failed }
  54.  function DeleteProfileString(Section : pChar;
  55.                               Entry : pChar
  56.                               ) : boolean;
  57.  
  58. {Explicitly read and write the INI file }
  59.   procedure ReadINIFile(Name : pChar);
  60.   procedure WriteINIFile(Name : pChar);
  61.  
  62. { Display to screen or print the current INI file }
  63.   procedure DisplayINIFile;
  64.   procedure PrintINIFile;
  65.  
  66. { Status and initialization routines }
  67. function INI_GetUpdateFlag : boolean;  { current setting of UpdateNow flag }
  68. procedure INI_SetUpdateFlag(F : boolean);  { Change UpdateNow flag }
  69.  
  70. implementation
  71.  
  72.   uses Objects;
  73.  
  74.   const
  75.        Dirty : boolean = FALSE;
  76.        Open : boolean = FALSE;
  77.        UpdateNow : boolean = FALSE;
  78.  
  79.   type
  80.       pEntryObj = ^tEntryObj;
  81.       tEntryObj = object(tObject)
  82.                     Entry : pChar;
  83.                     Data : pChar;
  84.                     constructor Init(E,D : string);
  85.                     destructor Done; virtual;
  86.                   end;
  87.  
  88.       pEntryList = ^tEntryList;
  89.       tEntryList = object(tSortedCollection)
  90.                      function KeyOf(Item : pointer) : pointer; virtual;
  91.                      function Compare(Key1,Key2 : pointer) : integer; virtual;
  92.                    end;
  93.  
  94.       pSectionObj = ^tSectionObj;
  95.       tSectionObj = object(tObject)
  96.                       Section : pChar;
  97.                       EList : tEntryList;
  98.                       constructor Init(S : string);
  99.                       destructor Done; virtual;
  100.                     end;
  101.  
  102.       pSectionList = ^tSectionList;
  103.       tSectionList = object(tSortedCollection)
  104.                      function KeyOf(Item : pointer) : pointer; virtual;
  105.                      function Compare(Key1,Key2 : pointer) : integer; virtual;
  106.                    end;
  107.  
  108.  
  109.   var
  110.      INIFile : text;
  111.      INIFName : pChar;
  112.      LineBuf : string;
  113.      INIList : tSectionList;
  114.      Output : text;
  115.  
  116.   constructor tEntryObj.Init;
  117.  
  118.     begin
  119.       getmem(Entry,length(E)+1); StrPCopy(Entry,E);
  120.       getmem(Data,length(D)+1); StrPCopy(Data,D);
  121.     end;
  122.  
  123.   destructor tEntryObj.Done;
  124.  
  125.     begin
  126.       freemem(Entry,strlen(Entry)+1);
  127.       freemem(Data,strlen(Data)+1);
  128.       inherited Done;
  129.     end;
  130.  
  131.   constructor tSectionObj.Init;
  132.  
  133.     begin
  134.       getmem(Section,length(S)+1); StrPCopy(Section,S);
  135.       EList.Init(10,4);
  136.     end;
  137.  
  138.   destructor tSectionObj.Done;
  139.  
  140.     begin
  141.       freemem(Section,strlen(Section)+1);
  142.       EList.FreeAll;
  143.       inherited Done;
  144.     end;
  145.  
  146.   function tEntryList.KeyOf(Item : pointer) : pointer;
  147.  
  148.     begin
  149.       KeyOf := pChar(pEntryObj(Item)^.Entry);
  150.     end;
  151.  
  152.   function tEntryList.Compare(Key1,Key2 : pointer) : integer;
  153.  
  154.     begin
  155.       Compare := strcomp(pChar(Key1),pChar(Key2));
  156.     end;
  157.  
  158.   function tSectionList.KeyOf(Item : pointer) : pointer;
  159.  
  160.     begin
  161.       KeyOf := pChar(pSectionObj(Item)^.Section);
  162.     end;
  163.  
  164.   function tSectionList.Compare(Key1,Key2 : pointer) : integer;
  165.  
  166.     begin
  167.       Compare := strcomp(pChar(Key1),pChar(Key2));
  168.     end;
  169.  
  170.   procedure LTrim(var S : string);
  171.  
  172.     var
  173.        i : integer;
  174.  
  175.     begin
  176.       i := 1;
  177.       repeat
  178.         if S[i] = ' ' then delete(S,i,1);
  179.       until S[i] <> ' ' ;
  180.     end;
  181.  
  182.   procedure RTrim(var S : string);
  183.  
  184.     var
  185.        i : integer;
  186.  
  187.     begin
  188.       i := length(S);
  189.       while S[i] = ' ' do dec(i);
  190.       S[0] := chr(i);
  191.     end;
  192.  
  193.   procedure ReadINIFile(Name : pChar);
  194.  
  195.     var
  196.       CurSection : pSectionObj;
  197.       CurEntry : pEntryObj;
  198.       SecStr : string;
  199.       EntryStr : string;
  200.       DataStr : string;
  201.       i,j : integer;
  202.  
  203.     begin
  204.       IniList.Init(100,20);
  205.       getmem(INIFName,strlen(Name) + 1);
  206.       StrCopy(INIFName,Name);
  207.       assign(INIFile,Name); {$I-} reset(INIFile); {$I+}
  208.       if IOResult = 0 then
  209.       begin
  210.         CurSection := nil;
  211.         repeat
  212.           readln(INIFile,LineBuf);
  213.           if (length(LineBuf) > 0) then
  214.           begin
  215.             if pos('[',LineBuf) = 1 then
  216.             begin
  217.               if CurSection <> nil then INIList.Insert(CurSection);
  218.               SecStr := Copy(LineBuf,2,pos(']',LineBuf)-2);
  219.               CurSection := new(pSectionObj,Init(SecStr));
  220.             end
  221.             else
  222.             begin
  223.               i := pos('=',LineBuf);
  224.               if i > 0 then
  225.               begin
  226.                 EntryStr := Copy(LineBuf,1,i - 1);
  227.                 LTRim(EntryStr); RTrim(EntryStr);
  228.                 DataStr := Copy(LineBuf,i + 1,length(LineBuf));
  229.                 LTrim(DataStr); RTrim(DataStr);
  230.                 if length(DataStr) = 0 then DataStr := '  ';
  231.               end
  232.               else
  233.               begin
  234.                 EntryStr := LineBuf;
  235.                 LTrim(EntryStr); RTrim(EntryStr);
  236.                 DataStr := '';
  237.               end;
  238.               CurEntry := new(pEntryObj,Init(EntryStr,DataStr));
  239.               CurSection^.EList.Insert(CurEntry);
  240.             end;
  241.           end;
  242.         until EOF(INIFile);
  243.         INIList.Insert(CurSection);
  244.         close(INIFile);
  245.       end
  246.       else
  247.       begin
  248.         rewrite(INIFile);
  249.       end;
  250.     end;
  251.  
  252.   procedure ShowEntries(List : tEntryList);
  253.  
  254.     procedure ShowEntry(Item : pointer); far;
  255.  
  256.       begin
  257.         writeln(Output,pEntryObj(Item)^.Entry,'=',pEntryObj(Item)^.Data);
  258.       end;
  259.  
  260.     begin
  261.       List.ForEach(@ShowEntry);
  262.     end;
  263.  
  264.   procedure ShowINIFile;
  265.  
  266.     procedure SHowSection(Item : pointer); far;
  267.  
  268.       begin
  269.         writeln(Output,'[',pSectionObj(Item)^.Section,']');
  270.         ShowEntries(pSectionObj(Item)^.EList);
  271.       end;
  272.  
  273.     begin
  274.       IniList.ForEach(@ShowSection);
  275.     end;
  276.  
  277. { Write data to a .INI file. Returns TRUE if successful }
  278.   function WriteProfileString(Section : pChar; { section: [section] }
  279.                               Entry : pChar;   { entry:   entry=data }
  280.                               Data : pChar) : boolean;
  281.  
  282.     var
  283.        SObj : pSectionObj;
  284.        EObj : pEntryObj;
  285.        SIndex,
  286.        EIndex : integer;
  287.  
  288.     begin
  289.       if INIFName = nil then
  290.       begin
  291.         WriteProfileString := FALSE;
  292.         exit;
  293.       end;
  294.       SObj := new(pSectionObj,Init(StrPas(Section)));
  295.       EObj := new(pEntryObj,Init(StrPas(Entry),StrPas(Data)));
  296.       if INIList.Search(Section,SIndex) then  { find section title }
  297.       begin
  298.         SObj := pSectionObj(INIList.At(SIndex));
  299.         if SObj^.EList.Search(Entry,EIndex) then  { find entry }
  300.         begin
  301.           EObj := pEntryObj(SObj^.EList.At(Eindex));
  302.           StrPCopy(EObj^.Data,StrPas(Data));
  303.           SObj^.EList.AtPut(EIndex,EObj);
  304.         end
  305.         else
  306.         begin
  307.           SObj^.EList.Insert(Eobj);
  308.         end;
  309.       end
  310.       else
  311.       begin
  312.         INIList.Insert(SObj);
  313.         SObj^.Elist.Insert(EObj);
  314.       end;
  315.       Dirty := TRUE;
  316.       if UpdateNow then WriteINIFile(INIFName);
  317.       WriteProfileString := TRUE;
  318.     end;
  319.  
  320. { get data associated with 'entry', under 'section' }
  321. { Returns data in 'Target', or places 'Default' in target, if entry/section }
  322. { is not found. }
  323.   function ReadProfileString(Section : pChar;
  324.                              Entry : pChar;
  325.                              Default : pChar;  { default value if Entry not found }
  326.                              Target : pChar;   { where to put the answer }
  327.                              ByteCnt : integer { size of target buffer }
  328.                              ) : boolean;
  329.  
  330.     var
  331.        SObj : pSectionObj;
  332.        EObj : pEntryObj;
  333.        SIndex,EIndex : integer;
  334.        Result : pChar;
  335.  
  336.     begin
  337.       if INIFName = nil then
  338.       begin
  339.         ReadProfileString := FALSE;
  340.         exit;
  341.       end;
  342.       if target = nil then getmem(Target,ByteCnt);
  343.       if INIList.Search(Section,SIndex) then
  344.       begin
  345.         SObj := pSectionObj(INIList.At(SIndex));
  346.         if SObj^.Elist.Search(Entry,EIndex) then
  347.         begin
  348.           EObj := pEntryObj(SObj^.Elist.At(EIndex));
  349.           StrCopy(Target,EObj^.Data);
  350.           ReadProfileString := TRUE;
  351.         end
  352.         else
  353.         begin
  354.           StrCopy(target,Default);
  355.           ReadProfileString := FALSE;
  356.         end;
  357.       end
  358.       else
  359.       begin
  360.          StrCopy(Target,Default);
  361.         ReadPRofileString := FALSE;
  362.       end;
  363.     end;
  364.  
  365.   function DeleteProfileString(Section : pChar;
  366.                                Entry : pChar
  367.                                ) : boolean;
  368.  
  369.     var
  370.        SObj : pSectionObj;
  371.        EObj : pEntryObj;
  372.        SIndex,Eindex : integer;
  373.  
  374.     begin
  375.       if INIList.Search(Section,SIndex) then
  376.       begin
  377.         SObj := pSectionObj(INIList.At(Sindex));
  378.         if SObj^.EList.Search(Entry,EIndex) then
  379.         begin
  380.           SObj^.EList.AtFree(EIndex);
  381.           DeletePRofileString := TRUE;
  382.           Dirty := TRUE;
  383.           if UpdateNow then WriteINIFile(INIFName);
  384.         end
  385.         else
  386.         begin
  387.           DeleteProfileString := FALSE;
  388.         end;
  389.       end
  390.       else
  391.       begin
  392.         DeleteProfileString := FALSE;
  393.       end;
  394.     end;
  395.  
  396.  
  397.  
  398.   procedure WriteINIFile;
  399.  
  400.     begin
  401.       assign(OutPut,Name);
  402.       rewrite(Output);
  403.       ShowINIFile;
  404.       close(Output);
  405.       Dirty := FALSE;
  406.     end;
  407.  
  408.   procedure DisplayINIFile;
  409.  
  410.     begin
  411.       assign(Output,'CON'); Rewrite(OutPut);
  412.       ShowINIFile;
  413.     end;
  414.  
  415.   procedure PrintINIFile;
  416.  
  417.     begin
  418.       assign(Output,'LPT1'); rewrite(Output);
  419.       ShowINIFile;
  420.       writeln(Output,^L);
  421.     end;
  422.  
  423.   function INI_GetUpdateFlag : boolean;
  424.  
  425.     begin
  426.       INI_GetUpdateFlag := UpdateNow;
  427.     end;
  428.  
  429.   procedure INI_SetUpdateFlag;
  430.  
  431.     begin
  432.       UpdateNow := F;
  433.     end;
  434.  
  435. begin
  436.   INIFName := nil;
  437. end.
  438.  
  439.